<?php
declare(strict_types=1);

namespace SixShop\MakerBundle\Generator;

use Symfony\Component\Console\Style\SymfonyStyle;

class PhpCodeGenerator
{
    private string $templatesPath;
    
    /**
     * 排除的模板文件，这些模板由专门的生成器处理（一对多关系）
     */
    private array $excludedTemplates = [
        'src/Model/Model.php.tpl.php',       // 模型模板 - 由 MigrationMaker 中的 ModelGenerator 处理
        'src/Entity/Entity.php.tpl.php',     // 实体模板 - 由 MigrationMaker 中的 EntityGenerator 处理
        'src/Controller',                    // 控制器目录 - 由专门的控制器生成器处理
        'database/migrations',               // 迁移文件夹 - 由 MigrationGenerator 处理
    ];

    public function __construct()
    {
        $this->templatesPath = __DIR__ . '/../../templates';
    }

    /**
     * 生成PHP代码文件
     */
    public function generatePhpFiles(string $packageName, string $namespace, string $id, string $description, string $targetPath, SymfonyStyle $io): bool
    {
        try {
            $basePath = $this->getBasePath($packageName, $targetPath);
            
            // 准备模板变量
            $variables = [
                'namespace' => $namespace,
                'name' => $packageName,
                'id' => $id,
                'description' => $description
            ];

            // 获取所有需要生成的PHP文件模板
            $templateFiles = $this->getTemplateFiles();
            
            $io->section('生成PHP代码文件:');
            
            foreach ($templateFiles as $templateFile) {
                if (!$this->generateFileFromTemplate($templateFile, $basePath, $variables, $io)) {
                    return false;
                }
            }
            
            $io->success('PHP代码文件生成完成!');
            return true;
            
        } catch (\Exception $e) {
            $io->error('生成PHP代码文件时发生错误: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * 获取扩展基础路径
     */
    private function getBasePath(string $packageName, ?string $targetPath = null): string
    {
        if ($targetPath !== null) {
            return $targetPath;
        }
        
        // 默认路径
        $vendorDir = dirname(__DIR__, 5);
        return $vendorDir . '/runtime/extension/' . $packageName;
    }

    /**
     * 获取所有模板文件
     */
    private function getTemplateFiles(): array
    {
        $templates = [];
        $this->scanTemplateDirectory($this->templatesPath, '', $templates);
        return $templates;
    }

    /**
     * 递归扫描模板目录
     */
    private function scanTemplateDirectory(string $directory, string $relativePath, array &$templates): void
    {
        if (!is_dir($directory)) {
            return;
        }

        $items = scandir($directory);
        foreach ($items as $item) {
            if ($item === '.' || $item === '..') {
                continue;
            }

            $fullPath = $directory . '/' . $item;
            $currentRelativePath = $relativePath ? $relativePath . '/' . $item : $item;

            if (is_dir($fullPath)) {
                // 检查是否为排除的目录
                if ($this->isExcludedTemplate($currentRelativePath)) {
                    continue;
                }
                
                // 递归扫描子目录
                $this->scanTemplateDirectory($fullPath, $currentRelativePath, $templates);
            } elseif (is_file($fullPath) && str_ends_with($item, '.php.tpl.php')) {
                // 检查是否为排除的模板文件
                if ($this->isExcludedTemplate($currentRelativePath)) {
                    continue;
                }
                
                // 添加模板文件
                $templates[] = [
                    'template' => $currentRelativePath,
                    'target' => str_replace('.tpl.php', '', $currentRelativePath),
                    'fullPath' => $fullPath
                ];
            }
        }
    }

    /**
     * 从模板生成文件
     */
    private function generateFileFromTemplate(array $templateInfo, string $basePath, array $variables, SymfonyStyle $io): bool
    {
        $templatePath = $templateInfo['fullPath'];
        $targetPath = $basePath . '/' . $templateInfo['target'];
        
        // 确保目标目录存在
        $targetDir = dirname($targetPath);
        if (!is_dir($targetDir)) {
            if (!mkdir($targetDir, 0755, true)) {
                $io->error("无法创建目录: $targetDir");
                return false;
            }
        }

        // 如果文件已存在，询问是否覆盖
        if (file_exists($targetPath)) {
            if (!$io->confirm("文件已存在: {$templateInfo['target']}，是否覆盖?", false)) {
                $io->text("跳过文件: {$templateInfo['target']}");
                return true;
            }
        }

        // 提取变量到当前作用域
        // 命名空间双斜杆需要改为单斜杠
        $namespace = str_replace('\\\\', '\\', $variables['namespace']);
        $name = $variables['name'];
        $id = $variables['id'];
        $description = $variables['description'];

        // 生成文件内容
        ob_start();
        include $templatePath;
        $content = ob_get_clean();

        // 写入文件
        if (file_put_contents($targetPath, $content) !== false) {
            $io->text("✓ 生成文件: {$templateInfo['target']}");
            return true;
        } else {
            $io->error("✗ 无法写入文件: {$templateInfo['target']}");
            return false;
        }
    }

    /**
     * 获取模板文件列表（用于预览）
     */
    public function getTemplateList(): array
    {
        return $this->getTemplateFiles();
    }
    
    /**
     * 检查模板是否在排除列表中
     */
    private function isExcludedTemplate(string $templatePath): bool
    {
        foreach ($this->excludedTemplates as $excludedPattern) {
            // 支持精确匹配和前缀匹配
            if ($templatePath === $excludedPattern || str_starts_with($templatePath, $excludedPattern)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 设置排除的模板列表
     */
    public function setExcludedTemplates(array $excludedTemplates): self
    {
        $this->excludedTemplates = $excludedTemplates;
        return $this;
    }
    
    /**
     * 添加排除的模板
     */
    public function addExcludedTemplate(string $templatePath): self
    {
        if (!in_array($templatePath, $this->excludedTemplates)) {
            $this->excludedTemplates[] = $templatePath;
        }
        return $this;
    }
    
    /**
     * 移除排除的模板
     */
    public function removeExcludedTemplate(string $templatePath): self
    {
        $this->excludedTemplates = array_filter(
            $this->excludedTemplates, 
            fn($excluded) => $excluded !== $templatePath
        );
        return $this;
    }
    
    /**
     * 获取当前排除的模板列表
     */
    public function getExcludedTemplates(): array
    {
        return $this->excludedTemplates;
    }
}